﻿using System;
using System.Configuration;
using System.Collections.Generic;
using SharePoint.Security.ConfigAnalyzer.Engine.Base;
using SharePoint.Security.ConfigAnalyzer.Engine.Common;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint;

namespace SharePoint.Security.ConfigAnalyzer.Engine.Rules.SearchAdmin
{
    public class SiteCollectionAccounts : BaseRule
    {
        #region Overrides of BaseRule

        private string idealSiteCollectionAdminCount = null;
        private int intSiteAdminCount = 0;

        public SiteCollectionAccounts()
        {
            idealSiteCollectionAdminCount = ConfigurationSettings.AppSettings["IdealSiteCollectionAdminCount"];

            if (idealSiteCollectionAdminCount != null)
            {
                intSiteAdminCount = Convert.ToInt16(idealSiteCollectionAdminCount);
            }

            RuleInfo = new RuleInfo
            {
                Description = "Ensure the SharePoint application has the lowest number of Site Collection Adminisrator Accounts",
                Title = "Site Collection Administrators",
                ExpectedValue = string.Format("< {0}", (intSiteAdminCount + 1).ToString())
            };
        }

        public override void Validate()
        {
            var logger = Logger.Log;
            string spWebURI = string.Empty;
            int siteCollectionAdmin = 0;
            SPFarm spFarm = ObjectHelper.Farm;
            string logInfoMsg = string.Empty;

            foreach (SPService spServiceItem in spFarm.Services)
            {
                if (spServiceItem is SPWebService)
                {
                    SPWebService oWebService = (SPWebService)spServiceItem;
                    foreach (SPWebApplication spWebApp in oWebService.WebApplications)
                    {
                        SPSiteCollection siteCollections = spWebApp.Sites;
                        foreach (SPSite siteCollection in siteCollections)
                        {
                            try
                            {
                                SPSite site = new SPSite(siteCollection.Url);
                                SPWeb web = site.OpenWeb();
                                spWebURI = web.Url;
                                foreach (SPUser spUser in web.Users)
                                {
                                    if (spUser.IsSiteAdmin)
                                    {
                                        siteCollectionAdmin += 1;
                                    }
                                }
                            }
                            catch (UnauthorizedAccessException)
                            {
                                logger.Error("Site Collection Administrators Rule - Access denied for : " + spWebURI);
                                logInfoMsg = ". Refer log file for sites with Access Issues";
                                continue;
                            }
                        }
                    }
                }
            }

            if (siteCollectionAdmin <= intSiteAdminCount && siteCollectionAdmin > 0)
            {
                Status = Status.Pass;
            }
            else
            {
                Status = Status.Fail;
            }

            CurrentValue = siteCollectionAdmin.ToString() + logInfoMsg;
            }        

        #endregion
    }
}
